package com.newy.web.sys;

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.newy.core.BaseController;
import com.newy.core.util.Converter;
import com.newy.core.util.LangUtils;
import com.newy.core.web.AppContext;
import com.newy.domain.sys.Menu;
import com.newy.domain.sys.vo.MenuItem;
import com.newy.service.sys.MenuService;
import com.newy.service.sys.UtilService;


/**
 * 菜单管理控制器类
 * @author linzongxue
 *
 */
@Controller
@RequestMapping("sys/menu")
public class MenuController extends  BaseController{	
	@Resource private MenuService menuSvc;
	@Resource private UtilService utilSvc;

	/**
	 * 获取当前登陆用户的菜单，返回符合extjs格式的树形数据
	 */
	@RequestMapping("getUserMenus")
	public @ResponseBody List<Map<String, Object>> getUserMenus(){
		List<Menu> menus = menuSvc.getMenusOfUser(AppContext.getLoginUser());
		for (int i = menus.size() - 1; i > -1; i --){ //去除按钮
			if (menus.get(i).isButton()) menus.remove(i);
		}
		return this.toTreeData(menus, false);
	}
	
	/**
	 * 获取指定菜单的子菜单目录，用于菜单目录树
	 * @param node 父菜单ID，如果不是数字表示取第一层目录
	 */
	@RequestMapping("getMenuFolders") @ResponseBody
	public List<Map<String, Object>> getMenuFolders(String node){
		Long parentId = null;
		if (StringUtils.isNumeric(node)){
			parentId = Long.parseLong(node);
		}
		List<Menu> menus = menuSvc.getMenuFolderChildren(parentId);
		return new Converter()
			.addConstField("leaf", false)
			.changeField("qtip", "tooltip").toListOfMap(menus);
	}
	
	/**
	 * 获取功能树列表数据(适合extjs树形的数据结构)
	 */
	@RequestMapping("getTreeGridData")
	public @ResponseBody List<Map<String, Object>> getTreeGridData(String node){
		Long parentId = null;
		if (StringUtils.isNumeric(node)){
			parentId = Long.parseLong(node);
		}

		List<Menu> menus = menuSvc.getAllChildren(parentId);
		return new Converter()
			.addField("leaf", new Converter.Convert<Menu>() {
				public Object to(Menu src) {
					return src.isItem();
				}
			})
			.addField("buttons", new Converter.Convert<Menu>() {
				public Object to(Menu src) {
					return LangUtils.filterField(menuSvc.getMenuButtons(src.getId()), "text");
				}
			})
			.addConstField("checked", false)
			.toListOfMap(menus);
	}

	/**
	 * 获取所有菜单数据（树形结构），以供角色关联菜单时用
	 */
	@RequestMapping("getAllMenusTreeData") @ResponseBody
	public List<Map<String, Object>> getAllMenusTreeData(){
		return this.toTreeData(menuSvc.getAllMenus(), true);
	}
	
	@RequestMapping("saveMenuFolder")
	public @ResponseBody Menu saveMenuFolder(Menu menu){
		menuSvc.saveMenuFolder(menu);
		return menu;
	}
	
	/**
	 * 保存菜单项，包含了按钮
	 */
	@RequestMapping("saveMenuItem")
	public @ResponseBody Menu saveMenuItem(MenuItem menuItem){
		menuSvc.saveMenuItem(menuItem);
		return menuItem.getMenuItem();
	}

	@RequestMapping("getMenuItem")
	public @ResponseBody MenuItem getMenuItem(Long menuId){
		MenuItem menuItem = new MenuItem();
		menuItem.setMenuItem(menuSvc.getMenu(menuId));
		menuItem.setButtons(menuSvc.getMenuButtons(menuId));
		return menuItem;
	}
	
	/**
	 * 通过id获取菜单数据
	 * @param id 菜单id
	 * @param fullPath 是否要获取菜单名称的全路径
	 */
	@RequestMapping("get")
	public @ResponseBody Object get(Long id, Boolean fullPath){
		Menu menu = menuSvc.getMenu(id);
		if (fullPath != null){
			return new Converter().addField("fullPath", new Converter.Convert<Menu>(){
				public Object to(Menu src) {
					return utilSvc.getEntityAttrPath(src.getId(), "text", "parentId", src.getClass().getName());
				}
			}).toMap(menu);
		}
		return menu;
	}

	/**
	 * 获取指定菜单项的所有按钮
	 */
	@RequestMapping("getButtons")
	public @ResponseBody Object getButtons(Long menuId){
		return menuSvc.getMenuButtons(menuId);
	}
	
	@RequestMapping("delete")
	public @ResponseBody void delete(Long[] ids){
		menuSvc.delete(ids);
	}
	
	/**
	 * 获取js模块文件的树形结构数据
	 * @param node 父文件路径
	 */
	@RequestMapping("getJsModules")
	public @ResponseBody List<Map<String, Object>> getJsModules(String node){
		List<Map<String, Object>> modules = new ArrayList<Map<String, Object>>();
		String parentPath = node.equals("/") || node.equals("root") ? "" : node;
		for (File file : menuSvc.getJsModules(parentPath)){
			String name = file.getName().replaceFirst(".js$", "");
			Map<String, Object> item = new LinkedHashMap<String, Object>();
			item.put("id", (parentPath.length() > 0 ? parentPath + "/" : "") + name);
			item.put("text", file.getName().replaceFirst(".js$", ""));
			item.put("leaf", file.isFile());
			modules.add(item);
		}
		return modules;
	}

	/**
	 * 将菜单列表转换成符合extjs格式的树形数据
	 * @param menus 菜单对象列表，已按父菜单在子菜单的前面排好顺序
	 * @param checked 节点是否有checkbox
	 */
	@SuppressWarnings({ "unchecked", "rawtypes" })
	private List<Map<String, Object>> toTreeData(List<Menu> menus, boolean checked){
		List<Map<String, Object>> result = new ArrayList<Map<String, Object>>();
		//构造辅助map
		Map<Long, Map<String, Object>> mapHelper = new HashMap();
		//遍历所有菜单，构造树形结构（没有根节点的树）
		for (Menu menu : menus){
			//创建树节点
			Map<String, Object> node = new Converter()
				.changeField("qtip", "tooltip")
				.addConstField("leaf", true) //先假设都是叶子节点
				.toMap(menu);
			if (checked){
				node.put("checked", false);
			}
			//将节点添加到辅助map中
			mapHelper.put(menu.getId(), node);
			//从辅助map中获取父节点
			Map<String, Object> parentNode = mapHelper.get(menu.getParentId());
			//如果父节点为空，说明是第一层节点，直接放到结果列表中；
			//如果父节点不为空，将新节点添加到父节点中。
			if (parentNode == null){
				result.add(node);
			}
			else{
				List children = (List)parentNode.get("children");
				if (children == null){
					children = new ArrayList();
					parentNode.put("leaf", false); //父节点设置为非叶子节点
					parentNode.put("children", children);
				}
				children.add(node);
			}
		}
		return result;
	}
}
